package com.guldan.test;

import com.guldan.core.spring.ContextHolder;
import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Silas.
 * Date: 2016/10/2
 * Time: 15:35
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/spring/app-context-*"})
public class BaseTestCase {

    protected Logger log = LoggerFactory.getLogger(getClass());

    private static final String prefix = "/sql/";
    private static final String suffix = ".sql";

    @Autowired
    protected ConfigurableApplicationContext applicationContext;

    @Autowired
    protected JdbcTemplate jdbcTemplate;

    protected String testClassName;

    @Before
    public void refreshSchema() throws SQLException {
        ContextHolder.setCtx(applicationContext);
        testClassName = getClass().getName();
        String sqlResourcePath = findResource(prefix, suffix);
        Resource resource = applicationContext.getResource(sqlResourcePath);
        if (resource.exists()) {
            for (String sql : loadSql(resource)) {
                jdbcTemplate.update(sql);
                System.err.println(sql);
            }
        }
    }

    private List<String> loadSql(Resource sqlStatement) {
        List<String> sqlList = new ArrayList<String>();
        String aLine;
        StringBuffer sb = new StringBuffer();
        try {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(sqlStatement.getInputStream(), "UTF-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            while ((aLine = reader.readLine()) != null) {
                if (StringUtils.isBlank(aLine) || aLine.startsWith("--")) {
                    continue;
                }
                // when the last charactor is ";", add on it and remove the ";"
                if (StringUtils.lastIndexOf(aLine, ";") == aLine.length() - 1) {
                    sb.append(aLine.substring(0, aLine.length() - 1));
                    sqlList.add(sb.toString());
                    sb = new StringBuffer();
                } else {
                    sb.append(" ");
                    sb.append(aLine);
                }

            }
            reader.close();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return null;
        }
        return sqlList;
    }

    private final String findResource(String prefix, String suffix) {
        String candidate = testClassName.replace('.', '/');
        if (prefix != null && !prefix.endsWith("/")) {
            prefix = prefix + "/";
        }

        String resourceName = null;
        while (candidate.length() > 0) {
            resourceName = StringUtils.join(new String[]{prefix, candidate, suffix});
            if (applicationContext.getResource(resourceName).exists()) {
                return resourceName;
            }
            candidate = StringUtils.substringAfter(candidate, "/");
        }

        return resourceName;
    }

    @Test
    public void test() {
        System.out.println("Junit Test " + testClassName + " execute complete.");
    }

}
